package com.epfuse.cloud.common.redis.serializer.impl;

import com.epfuse.cloud.common.redis.serializer.AbstractRedisSerializer;
import com.epfuse.cloud.common.redis.serializer.annotation.EpfuseRedisSerializer;
import com.epfuse.cloud.common.redis.serializer.enums.SerializerType;
import lombok.extern.slf4j.Slf4j;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.serializer.support.DeserializingConverter;
import org.springframework.core.serializer.support.SerializingConverter;
import org.springframework.data.redis.serializer.SerializationException;
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;

/**
 * @ClassName JdkSerializer
 * @Description TODO
 * @Author 孙峰
 * @Date 2023/3/8 9:28
 */
@EpfuseRedisSerializer(serializer = SerializerType.JDK)
public class JdkSerializer extends AbstractRedisSerializer {
    private final Converter<Object, byte[]> serializer;
    private final Converter<byte[], Object> deserializer;

    /**
     * Creates a new {@link JdkSerializer} using the default class loader.
     */
    public JdkSerializer() {
        this(new SerializingConverter(), new DeserializingConverter());
    }

    /**
     * Creates a new {@link JdkSerializer} using a {@link ClassLoader}.
     *
     * @param classLoader the {@link ClassLoader} to use for deserialization. Can be {@literal null}.
     */
    public JdkSerializer(@Nullable ClassLoader classLoader) {
        this(new SerializingConverter(), new DeserializingConverter(classLoader));
    }

    /**
     * Creates a new {@link JdkSerializer} using a {@link Converter converters} to serialize and deserialize objects.
     *
     * @param serializer   must not be {@literal null} 一个转换器 ，它委托给 Serializer 将对象转换为字节数组
     * @param deserializer must not be {@literal null} 一个转换器 ，它委托给 Deserializer 将字节数组中的数据转换为对象。
     */
    public JdkSerializer(Converter<Object, byte[]> serializer, Converter<byte[], Object> deserializer) {

        Assert.notNull(serializer, "Serializer must not be null!");
        Assert.notNull(deserializer, "Deserializer must not be null!");

        this.serializer = serializer;
        this.deserializer = deserializer;
    }

    public Object deserialize(@Nullable byte[] bytes) {

        if (isEmpty(bytes)) {
            return null;
        }
        try {
            return deserializer.convert(bytes);
        } catch (Exception ex) {
            throw new SerializationException("Cannot deserialize", ex);
        }
    }

    @Override
    public byte[] serialize(@Nullable Object object) {
        if (isEmpty(object)) {
            return EMPTY_ARRAY;
        }
        try {
            return serializer.convert(object);
        } catch (Exception ex) {
            throw new SerializationException("Cannot serialize", ex);
        }
    }
}
